#! coding:utf-8

import numpy as np
import os
from web.app.util import extract_entity_by_dictionary, read_inquiry_mapping, read_index_mapping, parse_inquiry
from web.app.word_segmenter import Segmenter


current_path = '/home/ubuntu/data/web/app'


class VectorGeneration(object):
    def __init__(self, inquiry_mapping_file='/home/ubuntu/data/web/app/dictionary/inquiry_feature.txt',
                 disease_mapping_file='/home/ubuntu/data/web/app/dictionary/disease_feature.txt',
                 tongue_mapping_file='/home/ubuntu/data/web/app/dictionary/tongue_feature.txt'):
        if inquiry_mapping_file and os.path.isfile(inquiry_mapping_file):
            # 问题-选项与其向量下标的映射字典
            self._inquiry_mapping_dic, self._inquiry_vector_size = read_inquiry_mapping(inquiry_mapping_file)
        else:
            self._inquiry_mapping_dic = None
        if disease_mapping_file and os.path.isfile(disease_mapping_file):
            self._disease_mapping_dic, self._disease_vector_size = read_index_mapping(disease_mapping_file, '\t')
        else:
            self._disease_mapping_dic = None
        if tongue_mapping_file and os.path.isfile(tongue_mapping_file):
            self._tongue_mapping_dic, self._tongue_vector_size = read_index_mapping(tongue_mapping_file, '\t')
        else:
            self._tongue_mapping_dic = None
        self._segmenter = Segmenter(os.path.join(current_path, 'dictionary/disease_list.txt'))

    def represent_inquiry(self, inquiry_list, vec_size=0):
        """
        将问诊单信息向量化

        :param inquiry_list: 待向量化的问诊单列表，每个元素为元组，第一项为问题，第二项为选项列表
        :param vec_size: 向量维度
        :return: 返回问诊单信息的表示向量
        """
        if not self._inquiry_mapping_dic:
            raise Exception('The inquiry mapping dictionary is not specified.')
        if vec_size <= 0:
            vec_size = self._inquiry_vector_size
        res_vec = np.zeros(vec_size)
        if not inquiry_list:
            return res_vec
        for question, answers in inquiry_list:
            if question in self._inquiry_mapping_dic:
                for ans in answers:
                    idx = self._inquiry_mapping_dic[question].get(ans, -1)
                    if 0 <= idx < vec_size:
                        res_vec[idx] = 1
        return res_vec

    def _get_max_index(self):
        res = 0
        for v in self._inquiry_mapping_dic.values():
            for idx in v.values():
                if idx > res:
                    res = idx
        return res

    def represent_user_info(self, age, weight, height):
        """
        将患者基本信息向量化

        :param age: 患者年龄
        :param weight: 患者体重
        :param height: 患者身高
        :return: 返回基本信息的表示向量
        """
        age_vec = self._age_feature(age)
        bmi_vec = self._bmi_feature(weight, height)
        return np.concatenate((age_vec, bmi_vec))

    def _age_feature(self, age):
        if age is None:
            age = 0
        if not isinstance(age, (int, float)):
            raise ValueError('age must be a number')
        age_vec = np.zeros(8)
        if age < 0 or age > 100:
            age_vec[0] = 1
        elif age >= 60:
            age_vec[7] = 1
        else:
            age_vec[int(age) // 10 + 1] = 1
        return age_vec

    def _bmi_feature(self, weight, height):
        if weight is None or height is None:
            return np.asarray([0, 1, 0, 0])
        if not isinstance(weight, (int, float)) or not isinstance(height, (int, float)):
            raise ValueError('weight or height should be numbers')
        if float(height) == 0.0:
            return np.asarray([0, 1, 0, 0])
        bmi_vec = np.zeros(4)
        height = height / 100
        bmi = weight / height / height
        if bmi < 18.5:
            bmi_vec[0] = 1
        elif bmi < 24:
            bmi_vec[1] = 1
        elif bmi < 28:
            bmi_vec[2] = 1
        else:
            bmi_vec[3] = 1
        return bmi_vec

    def represent_report(self, report, vec_size=0):
        if not self._disease_mapping_dic:
            raise Exception('The disease mapping dictionary is not specified.')
        if vec_size <= 0:
            vec_size = self._disease_vector_size
        disease_names = extract_entity_by_dictionary(report, self._segmenter, self._disease_mapping_dic)
        vec = np.zeros(vec_size)
        for name in disease_names:
            idx = self._disease_mapping_dic.get(name, -1)
            if 0 <= idx < vec_size:
                vec[idx] = 1
        return vec

    def represent_tongue(self, tongue_feature, vec_size=0):
        if not self._tongue_mapping_dic:
            raise Exception('The tongue mapping dictionary is not specified.')
        if vec_size <= 0:
            vec_size = self._tongue_vector_size
        vec = np.zeros(vec_size)
        for i, val in enumerate(tongue_feature):
            key_str = '{0} {1}'.format(i, str(val).strip())
            idx = self._tongue_mapping_dic.get(key_str, -1)
            if 0 <= idx < vec_size:
                vec[idx] = 1
        return vec

    def generate_feature_vector(self, user_info, report, inquiry, tongue_feature):
        items = user_info.split(' ')
        if len(items) < 3:
            info_vec = np.zeros(12)
        else:
            age, weight, height = float(items[0]), float(items[1]), float(items[2])
            info_vec = self.represent_user_info(age, weight, height)

        report_vec = self.represent_report(report)
        inquiry_vec = self.represent_inquiry(parse_inquiry(inquiry))
        tongue_vec = self.represent_tongue(tongue_feature)
        return np.concatenate((info_vec, report_vec, inquiry_vec, tongue_vec))


if __name__ == '__main__':
    tx = r'/home/ubuntu/data/Image_Retrieval/notebook/pic.txt'
    import shutil

    path_file = r'/home/ubuntu/data/dieseas_test/0'
    f = open(tx,'r').readlines()
    for i in f:
        i = i.strip()
        shutil.copy(path_file+'/'+i,r'/home/ubuntu/data/Image_Retrieval/notebook/pics/'+i)